Week 10: Java
Introduction
- Cool +
- Exception
- Interfaces
- Threads
- Dynamic Loading
- ...
Arrays
Introduction
- If B inherits A
B[] b = new B[10]; A[] a = b; a[0] = new A; b[0].method()
- Having multiple aliases to updateable locations with different types is unsound!
- Standard solution: Disallow subtyping through arrays
- Java fixes the problem by checking each array assignment at runtime for type correctness
- Adds overhead on array computations
- arrays of primitive types unaffected
Exceptions
- If you encounter an unexpected error, what will you do?
- Out of memory
- A list that is supposed to be sorted is not
- Solution
- Add a new type (class) of exceptions
- Add new forms
try{ ... } catch(x) { cleanup }
throw exception
- When we encounter a try
- Mark current location in the stack
- When we throw an exception
- Unwind the stack to the first try
- Execute corresponding catch
- What happens to an uncaught exception thrown during object finalization?
- Methods must declare types of exceptions they may raise:
public void X() throws MyException
- Checked at compile time
- Some exceptions need not be part of the method signature
Interfaces
- Java programs can use interfaces to make it unnecessary for related classes to share a common abstract superclass or to add methods to Object.
- Methods in classes implementing interfaces need not be at fixed offsets.
- Dispatches e.f(...) where e has an interface type are more complex than usual
- Because methods don’t live at fixed offsets
- One approach
- Each class implementing an interface has a lookup table from method names to methods
- Hash method names for faster lookup
Coercions
- Java allows primitive types to be coerced in certain contexts.
- In
1 + 2.0, the int 1 is widened to a float 1.0
- A coercion is really just a primitive function the compiler inserts for you
- Java distinguishes two kinds of coercions & casts
- Widening: always succeed (int -> float)
- Narrowing may fail if data can’t be converted to desired type (float -> int, downcasts)
- Narrowing casts must be explicit
- Wideningcasts / coercions can be implicit
- Bool is the only type in Java for which there are no coercions/casts defined.
Threads
- Java has concurrency built in through threads
- Thread objects have class
Thread
- Synchronization obtains a lock on the object:
synchronized (x) { e } (lock x; e; unlock x;)
- In synchronized methods,
this is locked
- Even without synchronization, a variable should only hold values written by some thread
- Writes of values are atomic
- Violated for doubles (because double needs two words)
- Java concurrency semantics are difficult to understand in detail, particularly as to how they might be implemented on certain machines
Other Topics
- Java allows classes to be loaded at run time
- Type checking source takes place at compile time
- Bytecode verification takes place at run time
- Loading policies handle by a ClassLoader
- Classes may also be unloaded
- A class is initialized when a symbol in the class is first used
- Not when the class is loaded
- Delays initialization errors to a predictable point (when something in the class is referenced)
- Algo
- Lock the class object for the class
- If the same thread is already initializing this class, release lock and return
- If class already initialized, return normally
- Otherwise, mark initialization as in progress by this thread and unlock class
- Initialize superclass, fields (in textual order)
- But initialize static, final fields first
- Give every field a default value before initialization
- Any errors result in an incorrectly initialized class, mark class as erroneous
- If no errors, lock class, label class as initialized, notify threads waiting on class object, unlock class